#ifndef cathlibcpp_iomanip_H
#define cathlibcpp_iomanip_H

// File:       iomanip.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    approximation to ANSI C++ iomanip header


#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_istream_H
#include "istream.h"
#endif

#ifndef cathlibcpp_newcasts_H
#include "newcasts.h"
#endif

#ifndef cathlibcpp_ostream_H
#include "ostream.h"
#endif


// class smanip<Arg>

template<class Stream, class Arg>
class smanip
{
  friend basic_istream_char& operator>>(basic_istream_char& is, smanip<Stream, Arg> const& manip);
  friend basic_ostream_char& operator<<(basic_ostream_char& os, smanip<Stream, Arg> const& manip);

  public:

    smanip(Stream& (*f)(Stream&, Arg), Arg arg)
      : f_(f),
        arg_(arg)
      {}

    Stream& apply(Stream& s) const
      {
        // CFront thinks that f_ is a non-const mfn!!!
        return const_cast(smanip<Stream _ Arg>*, this)->f_(s, arg_);
      }

  private:

    Stream& (*f_)(Stream&, Arg);
    Arg arg_;
};


// inserters/extractors

template<class Stream, class Arg>
inline basic_istream_char& operator>>(basic_istream_char& is, smanip<Stream, Arg> const& manip)
{
  manip.apply(is);
  return is;
}

template<class Stream, class Arg>
inline basic_ostream_char& operator<<(basic_ostream_char& os, smanip<Stream, Arg> const& manip)
{
  manip.apply(os);
  return os;
}


// underlying manip fns

extern ios_base& __manipfn_resetiosflags(ios_base& str, ios_base::fmtflags mask);
extern ios_base& __manipfn_setiosflags(ios_base& str, ios_base::fmtflags mask);
extern ios_base& __manipfn_setbase(ios_base& str, int base);
extern ios_base& __manipfn_setprecision(ios_base& str, int n);
extern ios_base& __manipfn_setw(ios_base& str, int n);
extern basic_ios_char& __manipfn_setfill(basic_ios_char& str, int c);


// macro to ease the definition of standard manipulators

#undef  __DEFINE_MANIP
#define __DEFINE_MANIP(fn, Stream, Arg)                \
inline smanip<Stream, Arg> fn(Arg arg)                 \
{                                                      \
  return smanip<Stream, Arg>(__manipfn_ ## fn, arg);   \
}


// standard manipulators

__DEFINE_MANIP(resetiosflags, ios_base, ios_base::fmtflags);
__DEFINE_MANIP(setiosflags, ios_base, ios_base::fmtflags);
__DEFINE_MANIP(setbase, ios_base, int);
__DEFINE_MANIP(setprecision, ios_base, int);
__DEFINE_MANIP(setw, ios_base, int);
__DEFINE_MANIP(setfill, basic_ios_char, int);

#endif
